﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Linq.Expressions;
using System.Net.Http;
using System.Threading;
using Common.Logging;
using In.Api.Dto.DinnerWs;
using Newtonsoft.Json;
using Out.Service.Helpers;
using Out.Service.HttpClients;
using OutDbContext;
using Rmq.Center;

namespace Out.Service.Services
{
    public class BizDinnerOrder : IDisposable
    {
        //BillStatus状态 ，1支付中2支付失败3支付成功4退款中5退款成功6退款失败
        public enum BillStatus
        {
            支付中 = 1,
            支付失败 = 2,
            支付成功 = 3,
            退款中 = 4,
            退款成功 = 5,
            退款失败 = 6
        }


        //DinnerOrder订单状态，0未支付 1落单中 2落单失败 3退款中 4退款成功 5退款失败 6落单成功 7微信退餐中
        //8微信退餐失败 9微信退餐成功 10微信退餐退款中 11微信退餐退款失败 12微信退餐退款成功
        public enum OrderStatus
        {
            未支付 = 0,
            落单中 = 1,
            落单失败 = 2,
            退款中 = 3,
            退款成功 = 4,
            退款失败 = 5,
            落单成功 = 6,
            微信退餐中 = 7,
            微信退餐失败 = 8,
            微信退餐成功 = 9,
            微信退餐退款中 = 10,
            微信退餐退款失败 = 11,
            微信退餐退款成功 = 12,
            落单失败重新落单 = 13
        }


        /// <summary>
        /// 支付状态:0-未付款,1-已付款,2-退款中,3-已退款,4-退款失败
        /// </summary>
        public enum PayState
        {
            未付款 = 0,
            已付款 = 1,
            退款中 = 2,
            已退款 = 3,
            退款失败 = 4
        }


        private static readonly ILog Logger = LogManager.GetLogger(typeof (BizDinnerOrder));

        private static readonly object OrderNoLocker = new object();

        private readonly GdsfybjyWeiXinEntities _ctx;
        private int _orderId;
        private int _billId;
        private readonly string _openId;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="openId">用户openid</param>
        public BizDinnerOrder(string openId = "")
        {
            _ctx = new GdsfybjyWeiXinEntities();
            _openId = openId;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="orderId">订单Id</param>
        /// <param name="openId">用户openid</param>
        public BizDinnerOrder(int orderId, string openId = "")
        {
            _ctx = new GdsfybjyWeiXinEntities();
            _orderId = orderId;
            _openId = openId;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="billNo">订餐DinnerId</param>
        /// <param name="openId">用户OpenId</param>
        public BizDinnerOrder(string billNo, string openId = "")
        {
            _ctx = new GdsfybjyWeiXinEntities();
            var order = _ctx.DinnerBills.FirstOrDefault(x => x.BillNo == billNo);
            if (order != null) _billId = order.Id;
            _openId = openId;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="billId">订餐Billid</param>
        /// <param name="orderId">订餐OrderDinnerId</param>
        public BizDinnerOrder(int billId, int orderId)
        {
            _ctx = new GdsfybjyWeiXinEntities();
            _billId = billId;
            _orderId = orderId;
        }


        /// <summary>
        /// 获取住院病人
        /// </summary>
        /// <param name="patientId"></param>
        /// <returns></returns>

        public WardPatient GetWardPatient(string patientId)
        {
            return _ctx.WardPatients.FirstOrDefault(x => x.PatientId == patientId);
        }

        /// <summary>
        /// 获取订餐菜单列表
        /// </summary>
        /// <returns></returns>
        public List<DinnerFood> GetDinnerFoods()
        {
            return _ctx.DinnerFoods.Where(x =>
                x.RecStatus == 1 &&
                System.Data.Entity.SqlServer.SqlFunctions.DateDiff("d", DateTime.Now, x.Date) >= 0
                &&
                System.Data.Entity.SqlServer.SqlFunctions.DateDiff("n", x.Date + " " + x.HmtEndTime, DateTime.Now) <= 0
                )
                .OrderBy(x => x.Date)
                .ToList();
        }

        /// <summary>
        /// 保存订餐订单
        /// </summary>
        /// <param name="openId">微信openId</param>
        /// <param name="cardNo">就诊卡号</param>
        /// <param name="cardType">就诊卡类型</param>
        /// <param name="dinnerDate">订单日期</param>
        /// <param name="dinnerHmtId">餐别Id</param>
        /// <param name="dinnerHmtName">餐别名称</param>
        /// <param name="dinnerFpId">食物Id</param>
        /// <param name="dinnerFpName">食物名称</param>
        /// <param name="dinnerEndTime">结束时间</param>
        /// <param name="orderId">订单号</param>
        /// <param name="foodCount">食物数量</param>
        /// <param name="foodAmount">食物金额</param>
        /// <param name="dinnerItemLength">订单明细长度</param>
        /// <param name="items">订单明细列表</param>
        public ResResult<string> SaveDinnerOrder(string openId, string cardNo, int cardType, string dinnerDate, string dinnerHmtId, string dinnerHmtName, string dinnerFpId,
            string dinnerFpName, string dinnerEndTime, int orderId, int foodCount, decimal foodAmount, int dinnerItemLength,List<string> items)
        {
            try
            {
                var payState = PayState.未付款.ToInt32();
                var existDinnerOrder =
                    _ctx.DinnerOrders.IsStatus(OrderStatus.未支付).FirstOrDefault(x => x.Id == orderId 
                                                          && x.PayStatus == payState &&
                                                          x.DeleteStatus != 1);
                if (existDinnerOrder != null)
                {
                    existDinnerOrder.TotalMoney = foodAmount;
                    existDinnerOrder.FoodAmount = foodAmount;
                    existDinnerOrder.FoodCount = foodCount;
                    var existDinnerOrderItems = _ctx.DinnerOrderItems.Where(x => x.OrderId == orderId).ToList();
                    foreach (var dinnerOrderItem in existDinnerOrderItems)
                    {
                        _ctx.DinnerOrderItems.Remove(dinnerOrderItem);
                    }
                }
                else
                {
                    var orderNo = GenerateNewOrderNo();

                    #region 住院信息
                    string patientId = "";
                    string patientname = "";
                    string wardcode = "";
                    string wardname = "";
                    string wardextentname = "";
                    string wardextentcode = "";
                    string bedlabel = "";
                    var bizHospCard = new BizHospCard(openId);
                    var card = bizHospCard.GetLastestCard(cardNo, cardType);
                    if (card != null)
                    {
                        patientId = card.PatientId;
                    }
                    if (!string.IsNullOrEmpty(patientId))
                    {
                        var wardPatients = _ctx.WardPatients.Where(
                            x => x.PatientId == patientId).OrderByDescending(x => x.VisitId).Take(1).ToList();
                        if (wardPatients.Count > 0)
                        {
                            patientname = wardPatients[0].Name;
                            bedlabel = wardPatients[0].BedLabel;
                            wardname = wardPatients[0].WardName;
                            wardextentname = wardPatients[0].WardExtentName;
                            wardextentcode = wardPatients[0].WardExtentCode;
                            wardcode = wardPatients[0].WardCode;
                        }
                    }

                    #endregion

                    var dinnerOrder = new DinnerOrder
                    {
                        OpenId = openId,
                        CardType = cardType,
                        CardNo = cardNo,
                        DinnerType = 0,
                        OrderDate = DateTime.Now,
                        OrderNo = orderNo,
                        TotalMoney = foodAmount,
                        Address = "",
                        OrderStatus = 0,
                        PayStatus = 0,
                        CreateTime = DateTime.Now,
                        DinnerDate = dinnerDate,
                        FpId = dinnerFpId,
                        FpName = dinnerFpName,
                        HmtId = dinnerHmtId,
                        HmtName = dinnerHmtName,
                        HmtEndTime = dinnerEndTime,
                        FoodCount = foodCount,
                        FoodAmount = foodAmount,
                        DcBillNo = null,
                        DeleteStatus = 0,
                        BedLabel = bedlabel,
                        WardName = wardname,
                        WardExtentName = wardextentname,
                        PatientName = patientname,
                        WardCode = wardcode,
                        WardExtentCode = wardextentcode,
                        PatientId = patientId
                    };
                    dinnerOrder = _ctx.DinnerOrders.Add(dinnerOrder);
                    _ctx.SaveChanges();
                    orderId = dinnerOrder.Id;

                }
                for (int i = 0; i < dinnerItemLength; i++)
                {
                    string dinnerItem = items[i];
                    //按照id,name,price,count排列
                    string[] dinnerItems = dinnerItem.Split(',');
                    var model = new DinnerOrderItem
                    {
                        OrderId = orderId,
                        FoodId = dinnerItems[0],
                        FoodName = dinnerItems[1],
                        FoodUnitPrice = Decimal.Parse(dinnerItems[2]),
                        FoodCount = int.Parse(dinnerItems[3]),
                        FoodAmount = Decimal.Parse(dinnerItems[2])*int.Parse(dinnerItems[3])
                    };
                    _ctx.DinnerOrderItems.Add(model);
                }
                _ctx.SaveChanges();
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("保存订餐订单出错,信息：{0}", JsonConvert.SerializeObject(ex));
                return new ResResult<string>(Result.失败,ex.Message);
            }

            return new ResResult<string>(Result.成功);
        }

        /// <summary>
        /// 删除订单明细
        /// </summary>
        /// <param name="orderId">订单Id</param>
        /// <returns></returns>
        public ResResult<string> DeleteDinnerOrder(int orderId)
        {
            try
            {
                var payState = PayState.未付款.ToInt32();
                var existDinnerOrder = _ctx.DinnerOrders.IsStatus(OrderStatus.未支付).FirstOrDefault(x => x.Id == orderId
                && x.PayStatus == payState && x.DeleteStatus != 1);
                if (existDinnerOrder != null)
                {
                    var existDinnerOrderItems = _ctx.DinnerOrderItems.Where(x => x.OrderId == orderId);
                    foreach (var dinnerOrderItem in existDinnerOrderItems)
                    {
                        _ctx.DinnerOrderItems.Remove(dinnerOrderItem);
                    }
                    existDinnerOrder.DeleteStatus = 1;

                    //ctx.DinnerOrders.Remove(existDinnerOrder);
                }
                _ctx.SaveChanges();
            }
            catch(Exception ex)
            {
                Logger.ErrorFormat("删除订餐订单出错,信息：{0}", JsonConvert.SerializeObject(ex));
                return new ResResult<string>(Result.失败, ex.Message);
            }
            return new ResResult<string>(Result.成功);
        }


        /// <summary>
        /// 获取订餐Bill
        /// </summary>
        /// <returns></returns>
        public DinnerBill GetDinnerBill(int billId=0)
        {
            var id = billId > 0 ? billId : _billId;
            var order = _ctx.DinnerBills.FirstOrDefault(x => x.Id == id);
            return order;
        }

        /// <summary>
        /// 获取订餐明细
        /// </summary>
        /// <returns></returns>
        public DinnerOrder GetDinnerOrder()
        {
            var order = _ctx.DinnerOrders.FirstOrDefault(x => x.Id == _orderId);
            return order;
        }

        /// <summary>
        /// 获取用户的所有订单数据
        /// 只支持查询从指定日期开始10日内的订单
        /// </summary>
        /// <param name="startDt">查询开始日期</param>
        /// <param name="cardNo">就诊卡号</param>
        /// <returns></returns>
        public List<DinnerOrder> DinnerOrderList(DateTime startDt, string cardNo)
        {
            startDt = startDt.Date;
            var endDt = startDt.AddDays(10);
            var orders = _ctx.DinnerOrders.IsStatus(OrderStatus.落单成功).IsOpenId(_openId)
                .Where(
                    x => x.CardNo == cardNo && x.CreateTime >= startDt &&
                        x.CreateTime < endDt).ToList();

            return orders;
        }

        /// <summary>
        /// 得到为支付订单列表
        /// </summary>
        /// <param name="cardNo">卡号</param>
        /// <returns></returns>
        public List<DinnerOrder> DinnerOrderList(string cardNo)
        {
            var payState = PayState.未付款.ToInt32();
            return _ctx.DinnerOrders.IsStatus(OrderStatus.未支付).Where(x => x.OpenId == _openId && x.CardNo == cardNo 
            && x.PayStatus == payState && x.DeleteStatus != 1 &&
            System.Data.Entity.SqlServer.SqlFunctions.DateDiff("d", DateTime.Now, x.DinnerDate) >= 0 
            && System.Data.Entity.SqlServer.SqlFunctions.DateDiff("n", x.DinnerDate + " " + x.HmtEndTime, DateTime.Now) <= 0).OrderByDescending(x => x.Id).ToList();
        }

        /// <summary>
        /// 获取订餐明细
        /// </summary>
        /// <param name="orderId">订单号</param>
        /// <returns></returns>
        public List<DinnerOrderItem> DinnerOrderItems(int orderId)
        {
            return _ctx.DinnerOrderItems.Where(x => x.OrderId == orderId).ToList();
        }


        /// <summary>
        /// 生成订餐订单单号
        /// </summary>
        /// <returns></returns>
        public string GenerateNewOrderNo()
        {
            var orderNo = "WX" + DateTime.Now.Date.ToString("yyyyMMdd");
            lock (OrderNoLocker)
            {
                orderNo += (DateTime.Now - DateTime.Now.Date).TotalMilliseconds.ToString("00000000");
                Thread.Sleep(1);
            }

            return orderNo;
        }


        /// <summary>
        /// 执行缴费支付操作 (前提： 微信支付状态为 未支付（0））
        /// </summary>
        public ResResult<string> Paying(string clientIp, string orderIds)
        {
            string[] ids = orderIds.Split(',');
            var orderIdList = new List<int>();
            //解析多个订单号
            foreach (var id in ids)
            {
                int orderId;
                if (Int32.TryParse(id, out orderId))
                {
                    orderIdList.Add(orderId);
                }
            }

            var payState = PayState.未付款.ToInt32();
            //更新账单状态为 支付中(1) 或 支付成功（3）【前提：没有账单】
            var orders = _ctx.DinnerOrders.IsStatus(OrderStatus.未支付).Where(
                x =>
                    orderIdList.Contains(x.Id)  &&
                    x.PayStatus == payState).ToList();

            if (orders.Any())
            {
                decimal totalMoney = 0;
                var openId = "";
                var billNo = GenerateNewOrderNo();
                foreach (var order in orders)
                {
                    openId = order.OpenId;
                    totalMoney += order.TotalMoney.GetValueOrDefault();
                }
                var dinnerbill = new DinnerBill
                {
                    OpenId = openId,
                    BillNo = billNo,
                    BillStatus = BillStatus.支付中.ToInt32(),
                    TotalMoney = totalMoney,
                    CreateTime = DateTime.Now,
                    DeleteStatus = 0
                };
                dinnerbill = _ctx.DinnerBills.Add(dinnerbill);
                _ctx.SaveChanges();
                _billId = dinnerbill.Id;
                //费用为零或测试支付时
                //更新账单状态为 支付成功（3）
                if (dinnerbill.TotalMoney == 0)
                {
                    foreach (var order in orders)
                    {
                        order.BillId = _billId;
                        order.OrderStatus = OrderStatus.落单成功.ToInt32();
                        order.PayStatus = PayState.已付款.ToInt32();
                        order.PayTime = DateTime.Now;
                    }
                    dinnerbill.BillStatus = BillStatus.支付成功.ToInt32();
                    dinnerbill.WxTransactionId = "0";
                    dinnerbill.PayTime = DateTime.Now;
                    _ctx.SaveChanges();
                    return new ResResult<string>(Result.成功, "", "");
                }
                //更新订餐订单账单号
                foreach (var order in orders)
                {
                    order.BillId = _billId;
                }
                _ctx.SaveChanges();


                if (dinnerbill.BillStatus == BillStatus.支付中.ToInt32())
                {
                    // RMQ 16分钟后执行支付失败操作
                    var payFailedProducer = new OrderPayFailedProducer();
                    payFailedProducer.Publish(new OrderPayFailedMsg
                    {
                        OrderType = Rmq.Center.OrderType.点餐订单,
                        OrderId = dinnerbill.Id,
                        OrderStatus = new[] {BillStatus.支付中.ToInt32()}
                    }, 16*60*1000);

                    //组织 微信 js 支付方法 getBrandWCPayRequest 的参数
                    var payStartTime = System.DateTime.Now.ToString("yyyyMMddHHmmss");
                    var payExpireTime = System.DateTime.Now.AddMinutes(15).ToString("yyyyMMddHHmmss");

                    var payFee = (dinnerbill.TotalMoney*100).ToInt32().ToString();
                    var superOpenIds = ConfigurationManager.AppSettings["OpenIdsForPayMin"]
                        .Split(" , ", StringSplitOptions.RemoveEmptyEntries);
                    if (superOpenIds.Contains(dinnerbill.OpenId))
                    {
                        payFee = "1";
                    }

                    var payRequestParam = TenpayV2Helper.GenerateWxPayParameter("订餐缴费", "DL" + dinnerbill.BillNo,
                        payFee, clientIp, payStartTime, payExpireTime);

                    return new ResResult<string>(Result.成功, payRequestParam, "");
                }
                else if (dinnerbill.BillStatus == BillStatus.支付成功.ToInt32())
                {

                    return new ResResult<string>(Result.成功, "订单已缴费成功", "");
                }
                else
                {
                    return new ResResult<string>(Result.条件不足未执行);
                }

            }
            else
            {
                return new ResResult<string>(Result.条件不足未执行);
            }

        }

        /// <summary>
        ///用户退餐 取消缴费单支付(订单前提微信退餐成功)
        /// </summary>
        public ResResult<RefundResult> CancelPay(bool autoFeedback=true)
        {
            var order =
                _ctx.DinnerOrders.IsStatus(OrderStatus.微信退餐成功).FirstOrDefault(x => x.Id == _orderId);
            if (order != null)
            {
                order.OrderStatus = OrderStatus.微信退餐退款中.ToInt32();
                order.PayStatus = PayState.退款中.ToInt32();
                order.RefundReason = "用户退餐";
                _ctx.SaveChanges();

            }
            else
            {
                return new ResResult<RefundResult>(Result.条件不足未执行);
            }

            try
            {
                var dinnerBill = _ctx.DinnerBills.FirstOrDefault(x => x.Id == order.BillId);
                if (dinnerBill != null)
                {
                    //var paylog = _ctx.OrderNotifyLogs.OrderByDescending(x => x.Id).FirstOrDefault(x => x.OutTradeNo == "BL" + order.OrderNo);
                    var totalFee = (dinnerBill.TotalMoney*100).ToInt32();
                    var refundAmount = (order.TotalMoney*100).ToInt32();
                    //if (paylog != null && paylog.TotalFee.ToInt32OrDefault() != refundAmount)
                    //{
                    //    refundAmount = paylog.TotalFee.ToInt32OrDefault();
                    //}
                    var refundResult = TenpayV2Helper.DoRefund(order.OpenId, "DL" + dinnerBill.BillNo,
                        dinnerBill.WxTransactionId,
                        "DL" + order.OrderNo, totalFee, refundAmount);

                    //退款成功 4,10
                    //退款处理中 8 9 11
                    if (refundResult.RefundStatus == 4 || refundResult.RefundStatus == 10 ||
                        refundResult.RefundStatus == 8 || refundResult.RefundStatus == 9 ||
                        refundResult.RefundStatus == 11)
                    {
                        if (autoFeedback)
                        {
                            CancelPaySucceed(refundResult);
                        }

                        return new ResResult<RefundResult>(Result.成功, refundResult);
                    }
                    //退款失败 3，5，6
                    //转入代发 7
                    if (refundResult.RefundStatus == 7 ||
                        refundResult.RefundStatus == 3 || refundResult.RefundStatus == 5 ||
                        refundResult.RefundStatus == 6)
                    {
                        if (autoFeedback)
                        {
                            CancelPayFailed();
                        }
                        return new ResResult<RefundResult>(Result.失败, refundResult, "");
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用第三方支付退款Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                return new ResResult<RefundResult>(Result.未返回);
            }


            return new ResResult<RefundResult>(Result.未返回);
        }

        /// <summary>
        /// 用户退餐订餐明细退费成功的处理
        /// </summary>
        /// <param name="resultResult"></param>
        public void CancelPaySucceed(RefundResult resultResult)
        {
            var order =
                _ctx.DinnerOrders.IsStatus(OrderStatus.退款中).FirstOrDefault(x => x.Id == _orderId);
            if (order != null)
            {
                order.OrderStatus = OrderStatus.微信退餐退款成功.ToInt32();
                order.PayStatus = PayState.已退款.ToInt32();
                order.RefundTime = DateTime.Now;
                order.WxRefundId = resultResult.RefundId;
                _ctx.SaveChanges();
                var dinnerBill = _ctx.DinnerBills.FirstOrDefault(x => x.Id == order.BillId);
                //账单中扣除此笔款项
                if (dinnerBill != null)
                {
                    dinnerBill.TotalRefundMoney = dinnerBill.TotalRefundMoney.GetValueOrDefault() + order.TotalMoney;
                    _ctx.SaveChanges();
                    //通知his有一笔负交易
                    //todo需判断此操作是否成功
                    var result = PostDinnerBillToHis(order.CardNo, order.FoodCount.GetValueOrDefault(),
                        order.TotalMoney.GetValueOrDefault() * (-1), dinnerBill.BillNo, dinnerBill.WxTransactionId);
                    if (result.Result != Result.成功)
                    {
                        //RMQ 重新传送订单到HIS
                        var repostProducer = new OrderPickupingChkProducer();
                        repostProducer.Publish(new OrderPickupingChkMsg
                        {
                            OrderType = Rmq.Center.OrderType.订餐订单明细,
                            OrderId = order.Id,
                            OrderStatus = new[] { OrderStatus.微信退餐退款成功.ToInt32() }
                        }, 60 * 1000);
                    }
                }
                

                //TODO RMQ 发送用户退餐成功通知
                //TODO RMQ 发送发货通知，发货失败

            }
        }

        /// <summary>
        /// 用户退餐订餐明细退费失败的处理
        /// </summary>
        public void CancelPayFailed()
        {

            var order =
                _ctx.DinnerOrders.IsStatus(OrderStatus.退款中).FirstOrDefault(x => x.Id == _orderId);
            if (order != null)
            {
                order.OrderStatus = OrderStatus.微信退餐退款失败.ToInt32();
                order.PayStatus = PayState.退款失败.ToInt32();
                _ctx.SaveChanges();

                //TODO RMQ 发送发货通知，发货失败
            }

        }

        /// <summary>
        /// 执行落单操作 （前提：订单状态为 落单中（1））
        /// </summary>
        public ResResult<string> DoPrescription(bool autoFeedback = true)
        {
            List<DinnerOrderItem> orderItems;
            var order =
                _ctx.DinnerOrders.IsStatus(OrderStatus.落单中).FirstOrDefault(x => x.Id == _orderId);
            if (order != null)
            {
                orderItems = _ctx.DinnerOrderItems.Where(x => x.OrderId == order.Id).ToList();
            }
            else
            {
                return new ResResult<string>(Result.条件不足未执行);
            }

            #region 执行落单

            var result = new ResResult<RequestPlaceTheOrderResponse>();

            var request = new RequestPlaceTheOrderRequest();
            request.RqGuestCardno = order.CardNo;
            request.RqDay = order.DinnerDate;
            request.RqFpId = order.FpId.ToInt32();
            request.RqHmtId = order.HmtId.ToInt32();
            request.RqFoodNum = order.FoodCount.ToInt32();
            request.RqSumAmt = order.TotalMoney.GetValueOrDefault();
            request.IsEmployee = order.DinnerType.GetValueOrDefault();
            request.UserAmtWay = "1";
            //request.OnlyType = "1";
            request.OnlyCode = order.OrderNo;
            request.Foods = new List<RequestPlaceTheOrderRequest.Food>();
            foreach (var orderitem in orderItems)
            {
                request.Foods.Add(new RequestPlaceTheOrderRequest.Food
                {
                    FoodId = orderitem.FoodId.ToInt32(),
                    FoodNum = orderitem.FoodCount.GetValueOrDefault()
                });
            }
            RequestPlaceTheOrderResponse response;

            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg = httpClient.PostAsJsonAsync("DinnerWs/RequestPlaceTheOrder", request).Result;
                responseMsg.EnsureSuccessStatusCode();
                response = responseMsg.Content.ReadAsAsync<RequestPlaceTheOrderResponse>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用院内订单落单Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                //RMQ查询订餐落单订单状态
                //var repostProducer = new OrderPickupingChkProducer();
                //repostProducer.Publish(new OrderPickupingChkMsg
                //{
                //    OrderType = Rmq.Center.OrderType.订餐订单明细,
                //    OrderId = order.Id,
                //    OrderStatus = new[] { OrderStatus.落单中.ToInt32() }
                //}, 6 * 60 * 1000);
                return new ResResult<string>(Result.未返回);
            }

            //落单成功
            if (response.ResultCode == "2")
            {
                if (autoFeedback)
                {
                    DoPrescriptionFail("调用院内落单失败");
                }
                return new ResResult<string>(Result.未返回, response.ErrorMsg);
            }
            else if (response.ResultCode == "0")
            {
                if (autoFeedback)
                {
                    DoPrescriptionSuccess(response.BillId);
                }
                return new ResResult<string>(Result.成功);
            }
            //落单失败
            else
            {
                if (autoFeedback)
                {
                    DoPrescriptionError("调用院内落单失败");
                }
                return new ResResult<string>(Result.失败, response.ErrorMsg);

            }

            #endregion
        }


        /// <summary>
        /// 将点餐支付账单信息传送给His，（微信支付）
        /// </summary>
        /// <param name="cardNo">就诊卡号</param>
        /// <param name="amount">金额</param>
        /// <param name="price">单价</param>
        /// <param name="billNo">单号</param>
        /// <param name="billTransactionId">微信业务号</param>
        /// <returns></returns>
        public ResResult<PostDinnerBillToHisResponse> PostDinnerBillToHis(string cardNo, int amount, decimal price,
            string billNo, string billTransactionId)
        {
            var result = new ResResult<PostDinnerBillToHisResponse>();
            var card = _ctx.HospCards.FirstOrDefault(x => x.CardNo == cardNo && x.CardStatus == 1);
            if (card != null)
            {
                var request = new PostDinnerBillToHisRequest();
                request.PatientId = card.PatientId;
                request.Amount = amount;
                request.Price = price;
                request.BillNo = billNo;
                request.BillTransactionId = billTransactionId;
                PostDinnerBillToHisResponse response;

                try
                {
                    var httpClient = InHttpClient.GetClient();
                    var responseMsg = httpClient.PostAsJsonAsync("DinnerWs/PostDinnerBillToHis", request).Result;
                    responseMsg.EnsureSuccessStatusCode();
                    response = responseMsg.Content.ReadAsAsync<PostDinnerBillToHisResponse>().Result;
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("调用院内将点餐支付账单信息传送给His Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                    result.Result = Result.未返回;
                    return result;
                }

                result.Response = response;

                if (response.ResultCode == "0")
                {
                    result.Result = Result.成功;
                    return result;
                }
                else
                {
                    result.Result = Result.失败;
                    result.Message = response.ErrorMsg;
                    return result;
                }
            }
            else
            {
                result.Result = Result.失败;
                return result;
            }

        }


        public ResResult<PostDinnerBillToHisResponse> CallPostDinnerBillToHis(DinnerBill dinnerBill)
        {
            var dinnerOrders = _ctx.DinnerOrders.Where(x => x.BillId == dinnerBill.Id).ToList();
            int footCont = dinnerOrders.Sum(order => order.FoodCount.GetValueOrDefault());
            //通知his有一笔正交易
            var result = PostDinnerBillToHis(dinnerOrders[0].CardNo, footCont, dinnerBill.TotalMoney, dinnerBill.BillNo,
                dinnerBill.WxTransactionId);
            return result;
        }

        /// <summary>
        /// 执行缴费成功处理
        /// </summary>
        public void DoPrescriptionSuccess(string dcBillNo)
        {
            var order =
                _ctx.DinnerOrders.IsStatus(OrderStatus.落单中).FirstOrDefault(x => x.Id == _orderId);
            if (order != null)
            {
                var dinnerBill = _ctx.DinnerBills.FirstOrDefault(x => x.Id == order.BillId);
                if (dinnerBill != null && dinnerBill.BillStatus == 3)
                {
                    order.OrderStatus = OrderStatus.落单成功.ToInt32();
                    //修改his返回的订单流水
                    order.DcBillNo = dcBillNo;

                    _ctx.SaveChanges();

                    // TODO RMQ 发送用户挂号成功通知
                    // TODO RMQ 发送发货通知
                }

            }
        }

        public void DoPrescriptionFail(string remarik)
        {
            var order =
                _ctx.DinnerOrders.IsStatus(OrderStatus.落单中).FirstOrDefault(x => x.Id == _orderId );
            if (order != null)
            {
                var dinnerBill = _ctx.DinnerBills.FirstOrDefault(x => x.Id == order.BillId);
                if (dinnerBill != null && dinnerBill.BillStatus == 3)
                {
                    order.OrderStatus = OrderStatus.落单失败重新落单.ToInt32(); //落单失败，重新落单
                    order.PayStatus = 1;
                    order.RefundReason = "落单失败，重新落单";
                    _ctx.SaveChanges();

                    //RMQ查询订餐落单订单状态
                    //var repostProducer = new OrderPickupingChkProducer();
                    //repostProducer.Publish(new OrderPickupingChkMsg
                    //{
                    //    OrderType = Rmq.Center.OrderType.订餐订单明细,
                    //    OrderId = order.Id,
                    //    OrderStatus = new[] { OrderStatus.落单失败重新落单.ToInt32() }
                    //}, 6 * 60 * 1000);
                }
            }
        }

        /// <summary>
        /// 执行缴费失败处理
        /// </summary>
        public void DoPrescriptionError(string remarik)
        {
            var order =
                _ctx.DinnerOrders.IsStatus(OrderStatus.落单中).FirstOrDefault(x => x.Id == _orderId );
            if (order != null)
            {
                var dinnerBill = _ctx.DinnerBills.FirstOrDefault(x => x.Id == order.BillId);
                if (dinnerBill != null && dinnerBill.BillStatus == 3)
                {
                    order.OrderStatus = OrderStatus.落单失败.ToInt32();
                    order.RefundReason = "因落单失败而退款";
                    _ctx.SaveChanges();

                    if (order.TotalMoney > 0)
                    {
                        // RMQ 执行退款操作
                        var refundingProducer = new OrderRefundingProducer();
                        refundingProducer.Publish(new OrderRefundingMsg
                        {
                            OrderType = Rmq.Center.OrderType.订餐订单明细,
                            OrderId = order.Id,
                            Reason = 1,
                            OrderStatus = new[] {OrderStatus.落单失败.ToInt32()}
                        }, 1000);
                    }
                }

            }

        }

        ///  <summary>
        ///  缴费单支付成功(微信回调)的处理
        ///  </summary>
        /// <param name="payDt">支付成功时间</param>
        /// <param name="transactionId">支付交易号</param>
        public void PaySucceed(DateTime payDt, string transactionId)
        {
            var dinnerBill = _ctx.DinnerBills.FirstOrDefault(x => x.Id == _billId );
            if (dinnerBill != null)
            {
                var dinnerOrders = _ctx.DinnerOrders.Where(x => x.BillId == dinnerBill.Id).ToList();
                //先修改账单的状态位
                var refundOpenIds = ConfigurationManager.AppSettings["OpenIdsForMustRefund"].Split(" , ",
                    StringSplitOptions.RemoveEmptyEntries);
                var isFromRefundOpenId = refundOpenIds.Contains(dinnerBill.OpenId);
                if (dinnerBill.BillStatus == BillStatus.支付中.ToInt32() && isFromRefundOpenId == false)
                {
                    dinnerBill.BillStatus = BillStatus.支付成功.ToInt32();
                    dinnerBill.PayTime = payDt;
                    dinnerBill.WxTransactionId = transactionId;

                    int footCont = 0;
                    //再修改各个订单状态位
                    foreach (var order in dinnerOrders)
                    {
                        footCont += order.FoodCount.GetValueOrDefault();
                        if (order.OrderStatus == 0)
                        {
                            order.PayStatus = 1;
                            order.OrderStatus = 1;
                            order.PayTime = payDt;
                        }
                    }
                    _ctx.SaveChanges();
                    //通知his有一笔正交易
                    var result = PostDinnerBillToHis(dinnerOrders[0].CardNo, footCont, dinnerBill.TotalMoney, dinnerBill.BillNo,
                        transactionId);
                    if (result.Result != Result.成功)
                    {
                        //RMQ 重新传送订单到HIS
                        var repostProducer = new OrderPickupingChkProducer();
                        repostProducer.Publish(new OrderPickupingChkMsg
                        {
                            OrderType = Rmq.Center.OrderType.点餐订单,
                            OrderId = _billId,
                            OrderStatus = new[] { BillStatus.支付成功.ToInt32() }
                        }, 60 * 1000);
                    }
                }
                if (dinnerBill.BillStatus == BillStatus.支付成功.ToInt32() && isFromRefundOpenId == false)
                {
                    foreach (var order in dinnerOrders)
                    {
                        if (order != null && order.OrderStatus == 1)
                        {
                            var clOrderId = order.Id;
                            //执行落单操作
                            var repostProducer = new OrderPickupingChkProducer();
                            repostProducer.Publish(new OrderPickupingChkMsg
                            {
                                OrderType = Rmq.Center.OrderType.订餐订单明细,
                                OrderId = clOrderId,
                                OrderStatus = new[] { OrderStatus.落单中.ToInt32() }
                            }, 1000);
                        }
                    }

                    foreach (var order in dinnerOrders)
                    {
                        if (order != null && (order.OrderStatus == OrderStatus.落单失败.ToInt32())) //落单失败
                        {
                            var clOrderId = order.Id;

                            // RMQ 执行退款操作
                            var refundingProducer = new OrderRefundingProducer();
                            refundingProducer.Publish(new OrderRefundingMsg
                            {
                                OrderType = Rmq.Center.OrderType.订餐订单明细,
                                OrderId = clOrderId,
                                Reason = 1,
                                OrderStatus = new[] { OrderStatus.落单失败.ToInt32() }
                            }, 1000);
                        }
                    }
                }
                if (dinnerBill.BillStatus == BillStatus.支付失败.ToInt32() && isFromRefundOpenId == false)
                {
                    foreach (var order in dinnerOrders)
                    {
                        if (order != null)
                        {
                            order.OrderStatus = OrderStatus.落单失败.ToInt32();
                            order.PayStatus = PayState.已退款.ToInt32();
                        }
                    }
                    dinnerBill.PayTime = payDt;
                    dinnerBill.WxTransactionId = transactionId;   
                    _ctx.SaveChanges();

                    // RMQ 执行退款操作
                    var refundingProducer = new OrderRefundingProducer();
                    refundingProducer.Publish(new OrderRefundingMsg
                    {
                        OrderType = Rmq.Center.OrderType.点餐订单,
                        OrderId = _billId,
                        Reason = 1,
                        OrderStatus = new[] { BillStatus.支付失败.ToInt32() }
                    }, 1000);

                }
            }
        }

        /// <summary>
        /// 16分钟过后轮训订单状态，执行取消支付
        /// </summary>
        /// <returns></returns>
        public void PayFailed()
        {
            var billStatus = BillStatus.支付中.ToInt32();
            var dinnerbill = _ctx.DinnerBills.FirstOrDefault(
                x => x.Id == _billId && x.BillStatus == billStatus);
            if (dinnerbill != null)
            {
                var orders = _ctx.DinnerOrders.Where(x => x.BillId == _billId).ToList();
                foreach (var order in orders)
                {
                    order.BillId = null;
                }
                dinnerbill.DeleteStatus = 1;
                dinnerbill.BillStatus = BillStatus.支付失败.ToInt32();
                _ctx.SaveChanges();
            }
        }


        /// <summary>
        /// DinnerBill订单已关闭，直接退款。
        /// </summary>
        /// <param name="autoFeedback"></param>
        /// <returns></returns>
        public ResResult<RefundResult> BillRefunding(bool autoFeedback = true)
        {
            var billStatus = BillStatus.支付失败.ToInt32();
            var dinnerBill = _ctx.DinnerBills.FirstOrDefault(x => x.Id == _billId && x.BillStatus == billStatus);
            if (dinnerBill != null)
            {
                dinnerBill.BillStatus = BillStatus.退款中.ToInt32();
                _ctx.SaveChanges();

            }
            else
            {
                return new ResResult<RefundResult>(Result.条件不足未执行);
            }

            try
            {
                //var paylog = _ctx.OrderNotifyLogs.OrderByDescending(x => x.Id).FirstOrDefault(x => x.OutTradeNo == "BL" + order.OrderNo);
                var totalFee = (dinnerBill.TotalMoney*100).ToInt32();
                //if (paylog != null && paylog.TotalFee.ToInt32OrDefault() != refundAmount)
                //{
                //    refundAmount = paylog.TotalFee.ToInt32OrDefault();
                //}
                var refundResult = TenpayV2Helper.DoRefund(dinnerBill.OpenId, "DL" + dinnerBill.BillNo,
                    dinnerBill.WxTransactionId,
                    "DL" + dinnerBill.BillNo, totalFee, totalFee);

                //退款成功 4,10
                //退款处理中 8 9 11
                if (refundResult.RefundStatus == 4 || refundResult.RefundStatus == 10 ||
                    refundResult.RefundStatus == 8 || refundResult.RefundStatus == 9 || refundResult.RefundStatus == 11)
                {
                    if (autoFeedback)
                    {
                        BillRefundSucceed(refundResult);
                    }

                    return new ResResult<RefundResult>(Result.成功, refundResult);
                }
                //退款失败 3，5，6
                //转入代发 7
                if (refundResult.RefundStatus == 7 ||
                    refundResult.RefundStatus == 3 || refundResult.RefundStatus == 5 || refundResult.RefundStatus == 6)
                {
                    if (autoFeedback)
                    {
                        BillRefundFailed();
                    }
                    return new ResResult<RefundResult>(Result.失败, refundResult, "");
                }
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用第三方支付退款Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                return new ResResult<RefundResult>(Result.未返回);
            }


            return new ResResult<RefundResult>(Result.未返回);
        }

        /// <summary>
        /// 退费成功的处理
        /// </summary>
        /// <param name="resultResult"></param>
        private void BillRefundSucceed(RefundResult resultResult)
        {
            var billStatus = BillStatus.退款中.ToInt32();
            var dinnerBill =
                _ctx.DinnerBills.FirstOrDefault(x => x.Id == _orderId && x.BillStatus == billStatus);
            if (dinnerBill != null)
            {
                dinnerBill.BillStatus = BillStatus.退款成功.ToInt32();
                //账单中扣除此笔款项
                dinnerBill.TotalRefundMoney = dinnerBill.TotalMoney;
                dinnerBill.WxRefundId = resultResult.RefundId;
                _ctx.SaveChanges();


                //TODO RMQ 发送用户退费成功通知
                //TODO RMQ 发送发货通知，发货失败

            }
        }

        /// <summary>
        /// 退费失败的处理
        /// </summary>
        private void BillRefundFailed()
        {
            var billStatus = BillStatus.退款中.ToInt32();
            var dinnerBill =
                _ctx.DinnerBills.FirstOrDefault(x => x.Id == _orderId && x.BillStatus == billStatus);
            if (dinnerBill != null)
            {
                dinnerBill.BillStatus = BillStatus.退款失败.ToInt32();
                _ctx.SaveChanges();


                //TODO RMQ 发送用户退费成功通知
                //TODO RMQ 发送发货通知，发货失败

            }

        }


        /// <summary>
        /// 执行订餐明细退费操作
        /// </summary>
        /// <param name="autoFeedback">是否自动做成功/失败数据处理</param>
        /// <returns></returns>
        public ResResult<RefundResult> Refunding(bool autoFeedback = true)
        {
            var order = _ctx.DinnerOrders.IsStatus(OrderStatus.落单失败).FirstOrDefault(x => x.Id == _orderId);
            if (order != null)
            {
                order.OrderStatus = OrderStatus.退款中.ToInt32();
                order.PayStatus = PayState.退款中.ToInt32();

                _ctx.SaveChanges();

            }
            else
            {
                return new ResResult<RefundResult>(Result.条件不足未执行);
            }

            try
            {
                var dinnerBill = _ctx.DinnerBills.FirstOrDefault(x => x.Id == order.BillId);
                if (dinnerBill != null)
                {
                    //var paylog = _ctx.OrderNotifyLogs.OrderByDescending(x => x.Id).FirstOrDefault(x => x.OutTradeNo == "BL" + order.OrderNo);
                    var totalFee = (dinnerBill.TotalMoney*100).ToInt32();
                    var refundAmount = (order.TotalMoney*100).ToInt32();
                    //if (paylog != null && paylog.TotalFee.ToInt32OrDefault() != refundAmount)
                    //{
                    //    refundAmount = paylog.TotalFee.ToInt32OrDefault();
                    //}
                    var refundResult = TenpayV2Helper.DoRefund(order.OpenId, "DL" + dinnerBill.BillNo,
                        dinnerBill.WxTransactionId,
                        "DL" + order.OrderNo, totalFee, refundAmount);

                    //退款成功 4,10
                    //退款处理中 8 9 11
                    if (refundResult.RefundStatus == 4 || refundResult.RefundStatus == 10 ||
                        refundResult.RefundStatus == 8 || refundResult.RefundStatus == 9 ||
                        refundResult.RefundStatus == 11)
                    {
                        if (autoFeedback)
                        {
                            RefundSucceed(refundResult);
                        }

                        return new ResResult<RefundResult>(Result.成功, refundResult);
                    }
                    //退款失败 3，5，6
                    //转入代发 7
                    if (refundResult.RefundStatus == 7 ||
                        refundResult.RefundStatus == 3 || refundResult.RefundStatus == 5 ||
                        refundResult.RefundStatus == 6)
                    {
                        if (autoFeedback)
                        {
                            RefundFailed();
                        }
                        return new ResResult<RefundResult>(Result.失败, refundResult, "");
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用第三方支付退款Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                return new ResResult<RefundResult>(Result.未返回);
            }


            return new ResResult<RefundResult>(Result.未返回);
        }


        /// <summary>
        /// 订餐明细退费成功的处理
        /// </summary>
        /// <param name="resultResult"></param>
        private void RefundSucceed(RefundResult resultResult)
        {
            var order =
                _ctx.DinnerOrders.IsStatus(OrderStatus.退款中).FirstOrDefault(x => x.Id == _orderId);
            if (order != null)
            {
                order.OrderStatus = OrderStatus.退款成功.ToInt32();
                order.PayStatus = PayState.已退款.ToInt32();
                order.RefundTime = DateTime.Now;
                order.WxRefundId = resultResult.RefundId;
                var dinnerBill = _ctx.DinnerBills.FirstOrDefault(x => x.Id == order.BillId);
                _ctx.SaveChanges();
                //账单中扣除此笔款项
                if (dinnerBill != null)
                {
                    dinnerBill.TotalRefundMoney = dinnerBill.TotalRefundMoney.GetValueOrDefault() + order.TotalMoney;
                    _ctx.SaveChanges();
                    //通知his有一笔负交易
                    //todo需判断此操作是否成功
                    var result = PostDinnerBillToHis(order.CardNo, order.FoodCount.GetValueOrDefault(),
                        order.TotalMoney.GetValueOrDefault() * (-1), dinnerBill.BillNo, dinnerBill.WxTransactionId);
                    if (result.Result != Result.成功)
                    {
                        //RMQ 重新传送订单到HIS
                        var repostProducer = new OrderPickupingChkProducer();
                        repostProducer.Publish(new OrderPickupingChkMsg
                        {
                            OrderType = Rmq.Center.OrderType.订餐订单明细,
                            OrderId = order.Id,
                            OrderStatus = new[] { OrderStatus.退款成功.ToInt32() }
                        }, 60 * 1000);

                    }
                }
                

                //TODO RMQ 发送用户退费成功通知
                //TODO RMQ 发送发货通知，发货失败

            }
        }

        /// <summary>
        /// 订餐明细退费失败的处理
        /// </summary>
        private void RefundFailed()
        {
            var order =
                _ctx.DinnerOrders.IsStatus(OrderStatus.退款中).FirstOrDefault(x => x.Id == _orderId);
            if (order != null)
            {
                order.OrderStatus = OrderStatus.退款失败.ToInt32();
                order.PayStatus = PayState.退款失败.ToInt32();
                _ctx.SaveChanges();

                //TODO RMQ 发送发货通知，发货失败
            }

        }

        public ResResult<RequestBillStatusResponse> GetDinnerOrderStatus(bool autoFeedback = true)
        {
            var order =
                _ctx.DinnerOrders.IsStatus(OrderStatus.微信退餐中).FirstOrDefault(x => x.Id == _orderId );

            if (order == null)
            {
                return new ResResult<RequestBillStatusResponse>(Result.条件不足未执行);
            }

            //var dinnerBill = _ctx.DinnerBills.FirstOrDefault(x => x.Id == order.BillId);
            var request = new RequestBillStatusRequest();
                request.CardNo = order.CardNo;
                RequestBillStatusResponse response;

                try
                {
                    var httpClient = InHttpClient.GetClient();
                    var responseMsg = httpClient.PostAsJsonAsync("DinnerWs/RequestBillStatus", request).Result;
                    responseMsg.EnsureSuccessStatusCode();
                    response = responseMsg.Content.ReadAsAsync<RequestBillStatusResponse>().Result;
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("调用院内查询订单状态Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                    return new ResResult<RequestBillStatusResponse>(Result.未返回);

                }
                //重新获取order值
                order = _ctx.DinnerOrders.FirstOrDefault(x => x.Id == _orderId);

                if (response.ResultCode == "0")
                {
                    var billStatuses = response.BillStatuses;
                    bool isCancel =
                        billStatuses.Any(
                            billStatus =>
                                order != null && (billStatus.BillId == order.DcBillNo && billStatus.IsCanceled == 1));

                    //已退餐，则退钱
                    if (isCancel)
                    {
                        if (order != null)
                        {
                            if (order.OrderStatus == OrderStatus.微信退餐中.ToInt32())
                            {
                                order.OrderStatus = OrderStatus.微信退餐成功.ToInt32(); //退餐成功
                                _ctx.SaveChanges();
                            }
                            if (order.TotalMoney > 0)
                            {
                                // RMQ 执行退款操作,Cancel
                                var refundingProducer = new OrderRefundingProducer();
                                refundingProducer.Publish(new OrderRefundingMsg
                                {
                                    OrderType = Rmq.Center.OrderType.订餐订单明细,
                                    OrderId = order.Id,
                                    Reason = 1,
                                    OrderStatus = new[] {OrderStatus.微信退餐成功.ToInt32()}
                                }, 1000);
                            }
                        }
                    }
                    else
                    {
                        //执行退餐操作
                        var cancelRequest = new RequestCancelBillRequest();
                        if (order != null)
                        {
                            cancelRequest.BillId = order.DcBillNo;
                            RequestCancelBillResponse cancelResponse;

                            try
                            {
                                var httpClient = InHttpClient.GetClient();
                                var responseMsg =
                                    httpClient.PostAsJsonAsync("DinnerWs/RequestCancelBill", cancelRequest).Result;
                                responseMsg.EnsureSuccessStatusCode();
                                cancelResponse = responseMsg.Content.ReadAsAsync<RequestCancelBillResponse>().Result;
                            }
                            catch (Exception ex)
                            {
                                Logger.ErrorFormat("调用院内取消订餐Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                                return new ResResult<RequestBillStatusResponse>(Result.未返回);
                            }
                            if (cancelResponse.ResultCode != "0")
                            {
                                order.OrderStatus = OrderStatus.微信退餐失败.ToInt32();
                                _ctx.SaveChanges();
                            }
                            else
                            {
                                order.OrderStatus = OrderStatus.微信退餐成功.ToInt32();
                                _ctx.SaveChanges();

                                if (order.TotalMoney > 0)
                                {
                                    // RMQ 执行退款操作,Cancel
                                    var refundingProducer = new OrderRefundingProducer();
                                    refundingProducer.Publish(new OrderRefundingMsg
                                    {
                                        OrderType = Rmq.Center.OrderType.订餐订单明细,
                                        OrderId = order.Id,
                                        Reason = 1,
                                        OrderStatus = new[] {OrderStatus.微信退餐成功.ToInt32()}
                                    }, 1000);
                                }
                            }
                        }
                    }
 
                    return new ResResult<RequestBillStatusResponse>(Result.成功, response);
                }
                else
                {
                    //如果查询结果异常，则返回未返回状态，等待下一次轮训
                    return new ResResult<RequestBillStatusResponse>(Result.未返回);
                }
            
        }

        /// <summary>
        /// 用户取消订餐操作,界面取消订餐
        /// </summary>
        public ResResult<string> CancelDinnerOrder()
        {
            var order =
                _ctx.DinnerOrders.IsStatus(OrderStatus.落单成功).FirstOrDefault(x => x.Id == _orderId 
                                                      &&
                                                      System.Data.Entity.SqlServer.SqlFunctions.DateDiff("d",
                                                          DateTime.Now, x.DinnerDate) >= 0 &&
                                                      System.Data.Entity.SqlServer.SqlFunctions.DateDiff("n",
                                                          x.DinnerDate + " " + x.HmtEndTime, DateTime.Now) <= 0);
            if (order == null)
            {
                return new ResResult<string>(Result.条件不足未执行, "订单不存在或已超出退餐时间限制！");
            }

            order.OrderStatus = OrderStatus.微信退餐中.ToInt32();
            _ctx.SaveChanges();

            //执行退餐操作
            var cancelRequest = new RequestCancelBillRequest();
            cancelRequest.BillId = order.DcBillNo;
            RequestCancelBillResponse cancelResponse;

            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg =
                    httpClient.PostAsJsonAsync("DinnerWs/RequestCancelBill", cancelRequest).Result;
                responseMsg.EnsureSuccessStatusCode();
                cancelResponse = responseMsg.Content.ReadAsAsync<RequestCancelBillResponse>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用院内取消订餐Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                //RMQ查询订餐落单订单状态
                var repostProducer = new OrderPickupingChkProducer();
                repostProducer.Publish(new OrderPickupingChkMsg
                {
                    OrderType = Rmq.Center.OrderType.订餐订单明细,
                    OrderId = order.Id,
                    OrderStatus = new[] { OrderStatus.微信退餐中.ToInt32() }
                }, 6 * 60 * 1000);
                return new ResResult<string>(Result.未返回);
            }
            if (cancelResponse.ResultCode != "0")
            {
                order.OrderStatus = OrderStatus.微信退餐失败.ToInt32();
                _ctx.SaveChanges();
            }
            else
            {
                order.OrderStatus = OrderStatus.微信退餐成功.ToInt32();
                _ctx.SaveChanges();

                if (order.TotalMoney > 0)
                {
                    // RMQ 执行退款操作,Cancel
                    var refundingProducer = new OrderRefundingProducer();
                    refundingProducer.Publish(new OrderRefundingMsg
                    {
                        OrderType = Rmq.Center.OrderType.订餐订单明细,
                        OrderId = order.Id,
                        Reason = 1,
                        OrderStatus = new[] {OrderStatus.微信退餐成功.ToInt32()}
                    }, 1000);
                }
            }

            return new ResResult<string>(Result.成功);
        }


        /// <summary>
        /// 资源释放
        /// </summary>
        public void Dispose()
        {
            _ctx.Dispose();
        }
    }

    public static class DinnerOrderExtensions
    {
        public static IQueryable<DinnerOrder> IsOpenId(this IQueryable<DinnerOrder> source, string openId)
        {
            if (string.IsNullOrEmpty(openId))
            {
                return source;
            }

            return source.Where(x => x.OpenId == openId);
        }

        public static IQueryable<DinnerOrder> IsStatus(this IQueryable<DinnerOrder> source,
                params BizDinnerOrder.OrderStatus[] orderStatuses)
        {
            Expression<Func<DinnerOrder, bool>> expression = x => true;

            foreach (var orderStatus in orderStatuses)
            {
                var intOrderStatus = (int)orderStatus;
                Expression<Func<DinnerOrder, bool>> exp = x => x.OrderStatus == intOrderStatus;
                var body = Expression.OrElse(expression.Body, exp.Body);
                expression = Expression.Lambda<Func<DinnerOrder, bool>>(body, expression.Parameters[0]);
            }

            return source.Where(expression);
        }

    }


}
